package soulkun.library.mvvm.component

import android.content.Context
import android.content.DialogInterface
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.databinding.DataBindingUtil
import androidx.databinding.ViewDataBinding
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.FragmentManager
import soulkun.library.utils.log.LogUtils
import java.util.concurrent.atomic.AtomicBoolean

/**
 * DialogFragment的生命周期
 * show() showDialog() ：onCreateView -> onViewCreated -> onStart -> onResume
 * dismiss() dismissAllowingStateLoss() ：onPause -> onStop -> onViewDestroyed
 * show 和 dismiss 都使用fragmentManager add和remove DialogFragment
 * 要实现复用则需要自定义show和dismiss
 */
abstract class BaseDataBindingDialogFragment<Binding : ViewDataBinding>(private val isNeedLogLifecycle: Boolean = false) : DialogFragment() {

    companion object {
        private const val TAG = "BaseDataBindingDialogFragment"
    }

    private var mBinding: Binding? = null
    protected lateinit var mContext: Context
    protected val status = AtomicBoolean(false) //默认为false，未展示

    override fun onAttach(context: Context) {
        super.onAttach(context)
        mContext = context
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onCreateView")
        mBinding = DataBindingUtil.inflate(inflater, setLayout(), container, false)
        mBinding!!.lifecycleOwner = viewLifecycleOwner
        return mBinding!!.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onViewCreated")
        requireDialog().window?.setBackgroundDrawable(null)
        doOnViewCreated()
    }

    override fun onStart() {
        super.onStart()
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onStart")
    }

    override fun onResume() {
        super.onResume()
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onResume")
        doOnResume()
    }

    override fun onDismiss(dialog: DialogInterface) {
        super.onDismiss(dialog)
        status.set(false)
        doOnDismiss()
    }

    override fun onPause() {
        super.onPause()
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onPause")
    }

    override fun onStop() {
        super.onStop()
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onStop")
    }

    override fun onDestroyView() {
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onDestroyView")
        doOnDestroyView()
        super.onDestroyView()
    }

    override fun onDestroy() {
        super.onDestroy()
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        if (isNeedLogLifecycle) LogUtils.logE(TAG, "onDetach")
    }

    fun requireDataBinding(): Binding {
        return mBinding ?: throw NullPointerException("mBinding is null")
    }

    /**
     * fragment show复用
     */
    fun showDialog(manager: FragmentManager, tag: String?) {
        if (!status.get()) {
            status.set(true)
            val superClass = this.javaClass.superclass.superclass
            val dismissField = superClass.getDeclaredField("mDismissed")
            val showField = superClass.getDeclaredField("mShownByMe")
            dismissField.isAccessible = true
            showField.isAccessible = true
            dismissField.set(this, false)
            showField.set(this, true)
            val fragment = manager.findFragmentByTag(tag)
            if (fragment != null) {
                manager.beginTransaction().show(fragment)
            } else {
                val fragmentTransaction = manager.beginTransaction()
                fragmentTransaction.add(this, tag)
                fragmentTransaction.commitAllowingStateLoss()
            }
        }
    }

    /**
     * commitNowAllowingStateLoss替代commitNow
     */
    override fun showNow(manager: FragmentManager, tag: String?) {
        if (!status.get()) {
            status.set(true)
            val superClass = this.javaClass.superclass.superclass
            val dismissField = superClass.getDeclaredField("mDismissed")
            val showField = superClass.getDeclaredField("mShownByMe")
            dismissField.isAccessible = true
            showField.isAccessible = true
            dismissField.set(this, false)
            showField.set(this, true)
            val fragmentTransaction = manager.beginTransaction()
            fragmentTransaction.add(this, tag)
            fragmentTransaction.commitNowAllowingStateLoss()
        }
    }

    @LayoutRes
    protected abstract fun setLayout(): Int

    protected abstract fun doOnViewCreated()

    protected abstract fun doOnResume()

    protected abstract fun doOnDismiss()

    protected abstract fun doOnDestroyView()

}